package com.maybach.util;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by houenxun on 15/7/9.
 */
public class MapUtil {
    public interface Parser<T> {
        public T parse(String str);
    }

    public static final Parser LONG_PARSER = new Parser<Long>() {
        @Override
        public Long parse(String str) {
            if (null == str) {
                return null;
            }
            return Long.parseLong(str);
        }
    };

    public static final Parser INTEGER_PARSER = new Parser<Integer>() {
        @Override
        public Integer parse(String str) {
            if (null == str) {
                return null;
            }
            return Integer.parseInt(str);
        }
    };

    public static final String DEFAULT_KEY_SPLIT = ":";
    public static final String DEFAULT_ITEM_SPLIT = ";";

    public static final Parser STRING_PARSER = new Parser<String>() {
        @Override
        public String parse(String str) {
            return str;
        }
    };

    /**
     * 使用默认分隔符将map转换成String
     *
     * @param map
     * @return
     */
    public static String toString(Map map) {
        return MapUtil.toString(map, DEFAULT_ITEM_SPLIT, DEFAULT_KEY_SPLIT);
    }


    /**
     * 将map转换成string
     *
     * @param map
     * @param itemSplit
     * @param keySplit
     * @return
     */
    public static String toString(Map map, String itemSplit, String keySplit) {
        if (null == map) {
            return null;
        }
        StringBuilder builder = new StringBuilder();
        for (Object key : map.keySet()) {
            builder.append(key).append(keySplit).append(null == map.get(key)? "" : map.get(key)).append(itemSplit);
        }
        if (builder.length() > 0) {
            return builder.substring(0, builder.length() - 1);
        }
        return "";
    }

    /**
     * 使用默认分隔符将string解析成map
     *
     * @param str
     * @param keyParser
     * @param valueParser
     * @param <K>
     * @param <V>
     * @return
     */
    public static <K, V> Map<K, V> parse(String str, Parser<K> keyParser, Parser<V> valueParser) {
        return parse(str, keyParser, valueParser, DEFAULT_ITEM_SPLIT, DEFAULT_KEY_SPLIT);

    }

    /**
     * 将string解析成map
     *
     * @param str
     * @param keyParser
     * @param valueParser
     * @param itemSplit
     * @param keySplit
     * @param <K>
     * @param <V>
     * @return
     */
    public static <K, V> Map<K, V> parse(String str, Parser<K> keyParser, Parser<V> valueParser, String itemSplit, String keySplit) {
        if (null == str) {
            return null;
        }
        Map<K, V> map = new HashMap<K, V>();
        String[] items = str.split(itemSplit);
        if (null != items) {
            for (String kv : items) {
                String[] kvArray = kv.split(keySplit);
                if (kvArray != null && kvArray.length == 2) {
                    map.put(keyParser.parse(kvArray[0].trim()), valueParser.parse(kvArray[1].trim()));
                }

            }
        }
        return map;
    }

    /**
     * 将列表转换成map
     * @param list
     * @param transfer
     * @param <K>
     * @param <V>
     * @return
     */
    public static <K,V> Map<K,V> mapList(List<V> list, Transfer<K,V> transfer){
        if(null == list){
            return null;
        }
        Map<K,V> map= new HashMap<K, V>();
        for(V v : list){
            map.put(transfer.transfer(v),v);
        }
        return map;

    }

    public interface  Transfer<K,V>{
       K transfer(V obj);
    }

    /**
     * 获取newMap相对oldMap的变化
     * @param oldMap
     * @param newMap
     * @param <K>
     * @param <V>
     * @return
     */
    public static <K,V> Map<K,V> getChangedMap(Map<K,V> oldMap, Map<K,V> newMap){
        Map<K,V> changeMap = new HashMap<K, V>();
        if(null == oldMap  && null == newMap){
            return changeMap;
        }
        if(null == oldMap){
            changeMap.putAll(newMap);
            return changeMap;
        }
        if(null == newMap){
            for(K key : oldMap.keySet()){
                changeMap.put(key, null);
            }
            return changeMap;
        }

        for(K key: oldMap.keySet()){
            if(null != oldMap.get(key) && null == newMap.get(key)){
                changeMap.put(key,null);
            }
        }

        for(K key: newMap.keySet()){
            if(!equals(newMap.get(key), oldMap.get(key))){
                changeMap.put(key, newMap.get(key));
            }
        }

        return changeMap;
    }


    public static <V> boolean equals(V v1, V v2){
        if(v1 == v2){
            return true;
        }
        if(null == v1 || null == v2){
            return false;
        }
        return v1.equals(v2);
    }

}
